package team.seekers.oj.group.service;

import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import team.seekers.oj.common.converter.BaseConvertUtils;
import team.seekers.oj.common.enums.ApiExceptionEnum;
import team.seekers.oj.common.util.AssertUtils;
import team.seekers.oj.group.dao.GroupExtensionDao;
import team.seekers.oj.group.entity.dao.GroupExtensionDO;
import team.seekers.oj.group.entity.dao.GroupExtensionDOField;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;


@Service
public class GroupExtensionService {

    @Autowired
    private GroupExtensionDao groupExtensionDao;

    public void addGroupParticipateCourse(long userId, long courseId) {
        setIncrementalUpdate(userId, GroupExtensionDOField.participateCourse(), String.valueOf(courseId));
    }

    public void addGroupParticipateContest(long userId, long contestId) {
        setIncrementalUpdate(userId, GroupExtensionDOField.participateContest(), String.valueOf(contestId));
    }

    public void addGroupParticipateHomework(long userId, long homeworkId) {
        setIncrementalUpdate(userId, GroupExtensionDOField.participateHomework(), String.valueOf(homeworkId));
    }

    private void setIncrementalUpdate(long groupId, String key, String incVal) {
        GroupExtensionDO groupExtensionDO = getGroupExtensionDO(groupId, key);
        Set<String> contestIdList = Optional.ofNullable(groupExtensionDO.getExtensionValue()).map(BaseConvertUtils::stringToSet).orElse(Sets.newHashSet());
        if (!contestIdList.add(incVal)) {
            return;
        }
        groupExtensionDO.setExtensionValue(BaseConvertUtils.setToString(contestIdList));
        AssertUtils.isTrue(groupExtensionDao.saveOrUpdate(groupExtensionDO), ApiExceptionEnum.SERVER_BUSY);
    }

    private GroupExtensionDO getGroupExtensionDO(long groupId, String key) {
        GroupExtensionDO groupExtensionDO = groupExtensionDao.lambdaQuery()
                .eq(GroupExtensionDO::getUserGroupId, groupId)
                .eq(GroupExtensionDO::getExtensionKey, key)
                .one();
        if (groupExtensionDO == null) {
            groupExtensionDO = GroupExtensionDO.builder().id(groupId).extensionKey(key).build();
        }
        return groupExtensionDO;
    }

    public List<Long> queryParticipateContest(long groupId) {
        GroupExtensionDO groupExtensionDO = getGroupExtensionDO(groupId, GroupExtensionDOField.participateContest());
        List<String> contestIdList = Optional.ofNullable(groupExtensionDO.getExtensionValue()).map(BaseConvertUtils::stringToList).orElse(Lists.newArrayList());
        return contestIdList.stream()
                .filter(StringUtils::isNumeric)
                .map(Long::parseLong)
                .collect(Collectors.toList());
    }

    public List<Long> queryParticipateHomework(long groupId) {
        GroupExtensionDO groupExtensionDO = getGroupExtensionDO(groupId, GroupExtensionDOField.participateHomework());
        List<String> contestIdList = Optional.ofNullable(groupExtensionDO.getExtensionValue()).map(BaseConvertUtils::stringToList).orElse(Lists.newArrayList());
        return contestIdList.stream()
                .filter(StringUtils::isNumeric)
                .map(Long::parseLong)
                .collect(Collectors.toList());
    }

    public List<Long> queryParticipateCourse(long groupId) {
        GroupExtensionDO groupExtensionDO = getGroupExtensionDO(groupId, GroupExtensionDOField.participateCourse());
        List<String> courseList = Optional.ofNullable(groupExtensionDO.getExtensionValue()).map(BaseConvertUtils::stringToList).orElse(Lists.newArrayList());
        return courseList.stream()
                .filter(StringUtils::isNumeric)
                .map(Long::parseLong)
                .collect(Collectors.toList());
    }
}